/*
 * INSANE - Interactive Structural Analysis Environment
 *
 * Copyright (C) 2003-2005
 * Universidade Federal de Minas Gerais
 * Escola de Engenharia
 * Departamento de Engenharia de Estruturas
 * 
 * Author's email :    insane@dees.ufmg.br
 * Author's website :  http://www.dees.ufmg.br/insane
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package br.ufmg.dees.insane.materialMedia.degeneration;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.ListIterator;

import br.ufmg.dees.insane.materialMedia.material.Material;
import br.ufmg.dees.insane.materialMedia.materialPoint.MaterialPoint;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.geometricProperties.DomainDiscretizedGeometricProperties;
import br.ufmg.dees.insane.util.geometricProperties.GeometricProperties;
import br.ufmg.dees.insane.util.geometricProperties.IGeometricPoint;


/**
 * Class representing Degeneration
 * @author roque, CENOURA!!!
 * @since Aug 2, 2005
 */
public class Degeneration implements Serializable{

    private static final long serialVersionUID = 1L;

    /** The label of this Degeneration. */
    protected String label;

    /** The original label of this Degeneration. */
    protected String originalLabel;

    /** The point which represents this Degeneration. */
    protected Representation representation;

    /** The list of material points of this Degeneration.*/
    protected ArrayList<MaterialPoint> materialPoints = new ArrayList<MaterialPoint>();

    /** Returns the label of this Degeneration.
     *@return The label of this Degeneration.
     */
    public String getLabel()
    {
	return this.label;
    }

    /** Sets the label of this Degeneration.
     *@param a The label of this Degeneration.
     */
    public void setLabel(String a)
    {
	this.label=a;
    }

    /** Returns the OriginalLabel of this Degeneration.
     *@return The OriginalLabel of this Degeneration.
     */
    public String getOriginalLabel()
    {
	return this.originalLabel;
    }

    /** Sets the OriginalLabel of this Degeneration.
     *@param a The OriginalLabel of this Degeneration.
     */
    public void setOriginalLabel(String a)
    {
	this.originalLabel=a;
    }

    /** Returns the representation of this Degeneration.
     * @return Returns the representation of this Degeneration.
     */
    public Representation getRepresentation() {
	return representation;
    }

    /** Sets the representation of this Degeneration.
     * @param representation The representation to set.
     */
    public void setRepresentation(Representation representation) {
	this.representation = representation;
    }

    /** Add a material point to the list of this Degeneration.
     *@param mp The material point to be added to the list of this Degeneration.
     */
    public void add(MaterialPoint mp){
	this.materialPoints.add(mp);
    }

    /** Remove a material point from the list of this Degeneration.
     *@param i The index of the material point to be removed from the list of this Degeneration.
     */
    public void remove(int i){
	this.materialPoints.remove(i);
    }

    /** Returns the number of materialpoints of this Degeneration.
     *@return The number of materialpoints of this Degeneration.
     */
    public int getNumberOfPoints(){
	return this.materialPoints.size();
    }

    /** Returns the materialPoints list
     * @return Returns the materialPoints list.
     */
    public ArrayList getMaterialPoints() {
	return materialPoints;
    }

    /** Returns the material point with the specified label.
     *@param label The specified label.
     *@return The material point with the specified label.
     */
    public MaterialPoint getMaterialPoint(String label) {
	ListIterator materialPoints = this.getMaterialPoints().listIterator();
	while (materialPoints.hasNext()) {
	    MaterialPoint mp = (MaterialPoint) materialPoints.next();
	    if (mp.getLabel().equals(label)) {
		return mp;
	    }
	}
	return null;
    }

    /** Returns a materialpoint of this Degeneration.
     *@param i The index of the material point.
     *@return A materialpoint of this Degeneration.
     */
    public MaterialPoint getMaterialPoint(int i){
	return (MaterialPoint)this.materialPoints.get(i);
    }

    public Material getMaterial(){
	return this.getMaterialPoint(0).getMaterial();
    }

    /** Returns the GeometricPoint of all materialPoints.
     * @return Returns the GeometricPoint of all materialPoints.
     */
    public ArrayList<IGeometricPoint> getGeometricPoints() {
	ArrayList<IGeometricPoint> aux = new ArrayList<IGeometricPoint>();
	ListIterator materialPoints = this.getMaterialPoints().listIterator();
	while (materialPoints.hasNext()) {
	    MaterialPoint mp = (MaterialPoint) materialPoints.next();
	    aux.add(mp.getGeometricPoint());
	}
	return aux;
    }

    /** Mounts the constitutive matrix.
     * @return The constitutive matrix.
     */
    public IMatrix mountC() {
	return null;
    }
    ;
    /** Mounts the tangent constitutive matrix.
     * @return The tangent constitutive matrix.
     */
    public IMatrix mountCt() {
	return null;
    }
    ;
    /** Mounts the secant constitutive matrix.
     * @return The secant constitutive matrix.
     */
    public IMatrix mountCs () {
	return null;
    }
    ;

    /** Mounts the DualInternalVariable Vector.
     * @param v the InternalVariable of this Degeneration.
     * @return The DualInternalVariable Vector of this Degeneration.
     */
    public IVector mountDualInternalVariableVector(IVector v) {
	return null;
    }
    ;

    /** Modify matrix of the Internal Variable Operator according to the material properties.
     *@param B The matrix representing the transformation between internal variable and state variable (B).
     *@return The matrix B modified.
     */
    public IMatrix internalVariableOperatorModifier(IMatrix B){
	return B;
    }

    /** Return the Internal Variables in a provided material point.
     *@param mp The material point.
     *@param dgintvar The degeneration internal variables vector.
     *@return sigma The IVector containing the InternalVariables in a provided material point.
     */
    public IVector getMPInternalVariables(String mplabel, IVector dgintvar) {
	MaterialPoint mp=this.getMaterialPoint(mplabel);
	IMatrix pointCoords = new IMatrix(3,1);
	pointCoords.setElement(0,0,mp.getPoint().x);
	pointCoords.setElement(1,0,mp.getPoint().y);
	pointCoords.setElement(2,0,mp.getPoint().z);
	IMatrix aux2=mp.getContinuousPointModel().getInternalVariableOperator(null,null,null,pointCoords);
	return aux2.mul(dgintvar);
    }

    /** Return the Dual Internal Variables in a provided material point.
     *@param mp The material point.
     *@param mpintvar The material point internal variables vector.
     *@return sigma The IVector containing the DualInternalVariables in a provided material point.
     */
    public IVector getMPDualInternalVariables(String mplabel, IVector mpintvar) {
	return this.getMaterialPoint(mplabel).getDualInternalVariables(mpintvar);
    }

    /** Updates this degeneration.
     */
    public void update(){
    }

    /**Inits this degeneration.
     */
    public void init() {
    	Representation repr = this.getRepresentation();
    	repr.init();
    	repr.getCm().init(repr.getPreviousVariables(), repr.getConstitutiveVariables(), repr.getAnalysisModel(), this.getMaterial());
    }

    /** Returns the GeometricProperties of this Degeneration.
     * @return Returns the GeometricProperties of this Degeneration.
     */
    public GeometricProperties getGeometricProperties () {
	GeometricProperties gp = new DomainDiscretizedGeometricProperties(this.getGeometricPoints());
	return gp;
    }
}
